﻿
using Xacml.Core;
using Xacml.Core.Interfaces;
using System;
using System.Xml;

namespace Xacml.Core.Policy
{
  public abstract class ApplyBaseReadWrite : XacmlElement
  {
    private string _functionId = string.Empty;
    private IExpressionCollectionReadWrite _arguments = new IExpressionCollectionReadWrite();

    public virtual string FunctionId
    {
      get
      {
        return this._functionId;
      }
      set
      {
        this._functionId = value;
      }
    }

    public virtual IExpressionCollectionReadWrite Arguments
    {
      get
      {
        return this._arguments;
      }
      set
      {
        this._arguments = value;
      }
    }

    protected ApplyBaseReadWrite(string functionId, IExpressionCollectionReadWrite arguments, XacmlVersion schemaVersion)
      : base(XacmlSchema.Policy, schemaVersion)
    {
      this._functionId = functionId;
      this._arguments = arguments;
    }

    protected ApplyBaseReadWrite(XmlReader reader, string nodeName, XacmlVersion schemaVersion)
      : base(XacmlSchema.Policy, schemaVersion)
    {
      if (reader != null)
      {
        if (!(reader.LocalName == nodeName) || !this.ValidateSchema(reader, schemaVersion))
          return;
        this._functionId = reader.GetAttribute("FunctionId");
        while (reader.Read())
        {
          switch (reader.LocalName)
          {
            case "Apply":
              if (!reader.IsEmptyElement && reader.NodeType != XmlNodeType.EndElement)
              {
                this._arguments.Add((IExpression) new ApplyElement(reader, schemaVersion));
                break;
              }
              break;
            case "Function":
              this._arguments.Add((IExpression) new FunctionElementReadWrite(reader, schemaVersion));
              break;
            case "AttributeValue":
              this._arguments.Add((IExpression) new AttributeValueElementReadWrite(reader, schemaVersion));
              break;
            case "SubjectAttributeDesignator":
              this._arguments.Add((IExpression) new SubjectAttributeDesignatorElement(reader, schemaVersion));
              break;
            case "ResourceAttributeDesignator":
              this._arguments.Add((IExpression) new ResourceAttributeDesignatorElement(reader, schemaVersion));
              break;
            case "ActionAttributeDesignator":
              this._arguments.Add((IExpression) new ActionAttributeDesignatorElement(reader, schemaVersion));
              break;
            case "EnvironmentAttributeDesignator":
              this._arguments.Add((IExpression) new EnvironmentAttributeDesignatorElement(reader, schemaVersion));
              break;
            case "AttributeSelector":
              this._arguments.Add((IExpression) new AttributeSelectorElement(reader, schemaVersion));
              break;
            case "VariableReference":
              this._arguments.Add((IExpression) new VariableReferenceElement(reader, schemaVersion));
              break;
          }
          if (reader.LocalName == nodeName && reader.NodeType == XmlNodeType.EndElement)
          {
            reader.Read();
            break;
          }
        }
      }
      else
        throw new Exception(Resource.ResourceManager[Resource.MessageKey.exc_invalid_node_name, new object[1]
        {
          (object) reader.LocalName
        }]);
    }

    public abstract void WriteDocument(XmlWriter writer);
  }
}
